"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
// NOTE:this is an plugin for css/scss or other preprocessor to compile and hot module replace
const fastify_plugin_1 = __importDefault(require("fastify-plugin"));
const path_1 = __importDefault(require("path"));
const fs_1 = __importDefault(require("fs"));
const crypto_1 = __importDefault(require("crypto"));
const component_compiler_utils_1 = require("@vue/component-compiler-utils");
const utils_1 = require("../utils");
const fsPromises = fs_1.default.promises;
const cssCacheMap = new Map();
exports.default = fastify_plugin_1.default((instance, options) => __awaiter(void 0, void 0, void 0, function* () {
    instance.addHook('preHandler', (request, reply) => __awaiter(void 0, void 0, void 0, function* () {
        const url = request.url.split('?')[0];
        if (utils_1.isCss.test(url) && request.query.import !== undefined) {
            console.debug(`enter css plugin`, request.query);
            try {
                let compileStyleResult;
                if (cssCacheMap.has(url)) {
                    compileStyleResult = cssCacheMap.get(url);
                }
                else {
                    const fileContent = yield fsPromises.readFile(path_1.default.join(options.root, url.substr(1)), { encoding: 'utf-8' });
                    compileStyleResult = yield compileCss(url, fileContent);
                }
                reply.type('application/javascript');
                return reply.send(genCssImportCode(url, compileStyleResult === null || compileStyleResult === void 0 ? void 0 : compileStyleResult.code));
            }
            catch (e) {
                console.error(`[tserve css]:`, e);
                if (e.code === 'ENOENT') {
                    reply.code(404)
                        .type('application/javascript')
                        .send(`no such file: ${url}.`);
                }
                else {
                    reply.code(500)
                        .type('application/javascript')
                        .send('error for reading css file');
                }
                return;
            }
        }
    }));
    instance.watcher.on('change', (filePath) => __awaiter(void 0, void 0, void 0, function* () {
        if (utils_1.isCss.test(filePath)) {
            const url = path_1.default.join(options.root, filePath);
            const fileContent = yield fsPromises.readFile(url, {
                encoding: 'utf-8'
            });
            yield compileCss(url, fileContent);
            instance.esConnections.forEach(conn => {
                const json = JSON.stringify({
                    id: url
                });
                conn.write(`event:css-update\ndata:${json}\n\n`);
            });
        }
    }));
    function compileCss(url, source) {
        return __awaiter(this, void 0, void 0, function* () {
            if (cssCacheMap.has(url)) {
                return cssCacheMap.get(url);
            }
            const result = yield component_compiler_utils_1.compileStyleAsync({
                filename: url,
                id: crypto_1.default.createHash('sha1').update(url).digest('hex').substr(0, 6),
                source,
                scoped: false
            });
            cssCacheMap.set(url, result);
            return result;
        });
    }
}));
function genCssImportCode(id, code) {
    return `import { updateStyle } from '/tserve/client.js'\n
          updateStyle('${id}',\`${code}\`)`;
}
